package com.wolf.antlr;

import com.wolf.antlr.java.JavaLexer;
import com.wolf.antlr.java.JavaParser;
import com.wolf.antlr.java.JavaParserBaseListener;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;

public class JavaSearcher {
    static List<MethodFragment> searchFunctions(String fileName, JavaListenerImp listener) {
        Lexer lexer;
        try {
            lexer = new JavaLexer(CharStreams.fromFileName(fileName, StandardCharsets.UTF_8));

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        TokenStream tokenStream = new CommonTokenStream(lexer);
        JavaParser parser = new JavaParser(tokenStream);
        ParseTree tree = parser.compilationUnit();
        ParseTreeWalker walker = new ParseTreeWalker();
        walker.walk(listener, tree);
        return listener.getMethodFragments();
    }

    public static void main(String[] args) {
        JavaListenerImp listener = new JavaListenerImp();
        String fileName = Main.parserArgs(args, listener);
        List<MethodFragment> methodFragments = searchFunctions(fileName, listener);
        methodFragments.forEach(methodFragment -> System.out.printf("%s, %s, %s, %s, %s\n",
                methodFragment.startIndex(),
                methodFragment.endIndex(),
                methodFragment.startLine(),
                methodFragment.endLine(),
                methodFragment.methodDeclaration()));
    }

    static class JavaListenerImp extends JavaParserBaseListener implements IListener {
        private String getMethodDeclaration(JavaParser.ClassBodyDeclarationContext ctx) {
            JavaParser.MethodDeclarationContext methodDeclarationContext = ctx.memberDeclaration().methodDeclaration();
            String functionName = methodDeclarationContext.identifier().getText();

            // 获取函数返回值
            String returnType = methodDeclarationContext.typeTypeOrVoid().getText();
            // 获取函数名称数组
            int bracketSize = methodDeclarationContext.LBRACK().size();
            // 获取函数参数列表
            JavaParser.FormalParametersContext parameters = methodDeclarationContext.formalParameters();
            ParseTree paramNodes = parameters.getChild(1);

            StringBuilder builder = new StringBuilder();
            builder.append('(');
            for (int i = 0; i < paramNodes.getChildCount(); i++) {
                ParseTree child = paramNodes.getChild(i);
                if (child.getChildCount() == 0) {
                    builder.append(", ");
                } else {
                    builder.append("%s %s".formatted(child.getChild(0).getText(), child.getChild(1).getText()));
                }
            }
            builder.append(')');

            String parameterList = builder.toString();
            // 拼接函数完整声明
            return "%s %s%s%s".formatted(returnType,
                    functionName, parameterList, " " + "[]".repeat(bracketSize)).strip();
        }

        @Override
        public void enterClassBodyDeclaration(JavaParser.ClassBodyDeclarationContext ctx) {
            super.enterClassBodyDeclaration(ctx);
            if (ctx.memberDeclaration().methodDeclaration() == null) {
                return;
            }
            String methodDeclaration = this.getMethodDeclaration(ctx);
            this.search(ctx, methodDeclaration);
        }

        @Override
        public void enterAnnotationMethodOrConstantRest(JavaParser.AnnotationMethodOrConstantRestContext ctx) {
            super.enterAnnotationMethodOrConstantRest(ctx);
            String annotationDeclaration = ctx.annotationMethodRest().identifier().getText();
            this.search(ctx, annotationDeclaration);
        }
    }
}
